package database;
import java.util.*;
import java.lang.ArrayIndexOutOfBoundsException;

/*
 * Class DatabaseSVN;
 * CS-271, Matthew Bone;
 * Project Members: Joe Cavallaro, Andrew Liao, Mark Johnson;
 * The project consists of class DatabaseSVN and nested class SomeObject.
 */

public class DatabaseSVN {
	
	public ArrayList<SomeObject> database = new ArrayList<SomeObject>();
	public ArrayList<String> categories;

	/*
	 * Default constructor method;
	 */
	public DatabaseSVN()
	{
		this.categories = new ArrayList<String>();
	}

	/*
	 * printObjectNames method;
	 * Prints the names of the "SomeObjects" contained in ArrayList "database";
	 */
	public void printObjectNames()
	{
		for(SomeObject s: database)
		{
			System.out.println(s.name);
		}
	}
	
	/*
	 * addObject method
	 * Receives: a parameter, String "name", the name for a new "SomeObject";
	 * Adds a new "SomeObject" to "database" and sets the SomeObject's name to "name";
	 */
	public void addObject(String string)
	{
		SomeObject newObject = new SomeObject();
		newObject.name = string;
		database.add(newObject);
	}
	
	/*
	 * removeObject method
	 * Receives: a parameter, String "name", the name of the "SomeObject" to be removed;
	 * Calls method, "nameSearch", with parameter "name", uses that result as the parameter for
	 * a call to the remove method on "database", which is an ArrayList; 
	 */
	public void removeObject(String name)
	{
		name = name.toLowerCase();
		database.remove(nameSearch2(name));
	}
	
	/*
	 * categorySearch method
	 * Receives: parameters "category"(the category to search in) and "toFind"(the String you're searching for;
	 * Prints names of all Objects that have that string in specified category.
	 */
	public void categorySearch(String category, String toFind)
	{
		boolean dataFound = false;;
		category = category.toLowerCase();
		int numCategory = getCatPlace(category);
		toFind = toFind.toLowerCase();
		System.out.println("The following Objects contain the data \"" + toFind + "\" in category \"category\":");
		for(SomeObject o: database)
		{
			//System.out.println("The following matches were found for " + toFind + ":");
			
			if(o.myStuff.get(numCategory).equals(toFind))
			{
				System.out.println(o.name);
				dataFound = true;
			}
		}
		if(dataFound == false)
		{
			System.out.println("None");
		}
	}
	
	/*
	 * nameSearch method
	 * Receives parameter, "name";
	 * Performs a search in database for an Object with certain name.
	 */
	public int nameSearch(String name)
	{
		boolean foundName = false;
		name = name.toLowerCase();
		for(SomeObject s: database)
		{
			int place = 0;
			if(s.name.equals(name))
			{
				s.printAll();
				foundName = true;
				return place;
			}
			place++;
		}
		if(foundName == false)
		{
			System.out.println("Invalid name entry.");
		}
		return -1;
	}
	
	/*
	 * nameSearch2 method
	 * Receives: parameter "name"
	 * Returns: the "SomeObject" in "database" with "name" that is equivalent to the "name" parameter;
	 */
	public SomeObject nameSearch2(String name)
	{
		name = name.toLowerCase();
		for(SomeObject s: database)
		{
			int place = 0;
			String theName = s.name;
			if(theName.equals(name))
			{
				return s;
			}
			place++;
		}
		return null;
	}
	
	/*
	 * addCategory method
	 * Receives: parameter "categoryName"
	 * Adds an additional element to ArrayList "categories" of a DatabaseSVN class object;
	 */
	public void addCategory(String categoryName)
	{
		categoryName = categoryName.toLowerCase();
		categories.add(categoryName);
		checkCategories();
	}
	
	/*
	 * removeCategory method;
	 * Receives: int "catNum";
	 * Removes the String in each SomeObject within "database" at index "catNum";
	 * Removes the String at index "catNum"
	 */
	public void removeCategory(int catNum)
	{
		for(SomeObject o: database)
		{
			o.myStuff.remove(catNum);
		}
		categories.remove(catNum);
	}	
	/*
	 * checkCategories method;
	 * Checks each SomeObject's mySuff ArrayList size against the size of ArrayList categories;
	 * If the SomeObject's myStuff ArrayList is smaller than the categories ArrayList,
	 * then the method adds empty strings to the objects until each SomeObject's myStuff
	 * ArrayList is the same size as the categories ArrayList; 
	 */
	public void checkCategories()
	{
		for(SomeObject s: database)
		{
			if(s.myStuff.size() < categories.size())
			{
				for(int i = s.myStuff.size(); i  < categories.size(); i++)
				{
					//s.myStuff.add(categories.get(i));
					s.myStuff.add(s.myStuff.size(), "");
				}
			}
		}
	}
	
	public int getCatPlace(String category)
	{
		category = category.toLowerCase();
		int index = 0;
		for(String s: categories)
		{
			if(s.equals(category))
			{
				return index;
			}
			else
			{
				index++;
			}
		}
		
		System.out.println("String not found");
		return -1;
	}
	
	public void printAllCategories(){
		if(categories.size() > 0)
		{
			for(String s: categories)
			{
				System.out.println(s);
				
			}
			System.out.println();
		}
		else
		{
			System.out.println("No Categories found");
		}
	}
	
	public void printAllObjectNames()
	{
		if(database.size() != 0)
		{
			for(SomeObject o: database)
			{
				System.out.print(o.name);
			}
		}
		else
		{
			System.out.println("The database is currently empty");
		}
	}
	
	public String printCategory(int index)
	{
		return categories.get(index);

	}
	
	public boolean categoryExist(String string)
	{
		string = string.toLowerCase();
		for(String s: categories)
		{
			if(s.equals(string))
			{
				return true;
			}
		}
		return false;
	}
	
	public boolean objectExist(String string)
	{
		string = string.toLowerCase();
		for(SomeObject o: database)
		{
			if(o.name.equals(string))
			{
				return true;
			}
		}
		return false;
	}
	
	public class SomeObject
	{		
		private String name;
		public ArrayList<String> myStuff;
		//When an "object" is constructed, it has an ArrayList
		//which contains a placeholder for each of the categories that
		//exist, as well as a string that holds the objects name.
		public SomeObject(String name, ArrayList<String> categories)
		{
			myStuff = new ArrayList<String>();
			for(String s: categories)
			{
				int i = 0;
				myStuff.set(i, null);
			
			
			name = name.toLowerCase();
			this.name = name;
			}
		}
		
		public SomeObject(String name)
		{
			myStuff = new ArrayList<String>();
			name = name.toLowerCase();
			this.name = name;
		}
		public SomeObject()
		{
			myStuff = new ArrayList<String>();
			this.name = null;
		}
		
		//Adds strings to myStuff
		//catAdd - Place in categories which corresponds
		//to where new string is to be added to in myStuff.
		public void addStuff(String category, String string)
		{
			int catAdd = getCatPlace(category);
			this.myStuff.set(catAdd, string);
		}
		public void printAll()
		{
			if(categories.size() == 0 || checkAllNull(this))
			{
				System.out.println("No data stored for \"" + this.name + "\".");
			}
			System.out.println("Name: " + this.name);
			System.out.println("All data for " + this.name + ":");
			for(int i = 0; i < categories.size(); i++)
			{
				if(checkNoData(this.myStuff.get(i)))
				{
					System.out.println(printCategory(i) + ": " + "(EMPTY)");
				}	
				System.out.println(printCategory(i) + ": " + this.myStuff.get(i));
			}
		}
		public boolean checkNoData(String string)
		{
			if(string.equals(null))
			{
				return true;
			}
			
			return false;
		}
		public boolean checkAllNull(SomeObject s)
		{
			boolean foundIt = false;
			for(int i = 0; i < categories.size() - 1; i++)
			{
				System.out.println("size equals: " + s.myStuff.size());
				if(!(s.myStuff.get(i).equals("")))
				{
					foundIt = true;
				}
			}
			return foundIt;
		}
	}
}
